package com.spider;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import com.spider.processor.ValueProcessor;


/**
 * 主要处理类
 * 
 * @author yan_li
 *
 */
public class Spider<T> {

    static HttpClient httpClient = HttpClients.createDefault();

    private ValueProcessor<T> processor;//匹配处理器

    private ArrayBlockingQueue<String> queue;//收集结果

    private String targeRegex;//匹配规则

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static Spider create(ValueProcessor processor, ArrayBlockingQueue<String> resultQueue, String targeRegex) {

        return new Spider(processor, resultQueue, targeRegex);
    }

    private Spider(ValueProcessor processor, ArrayBlockingQueue<String> queue, String targeRegex) {
        this.processor = processor;
        this.queue = queue;
        this.targeRegex = targeRegex;
    }

    /**
     * 正则匹配
     * 
     * @param regex
     * @param value
     * @return
     */
    private Matcher getMatcher(String regex, String value) {
        Pattern compile = Pattern.compile(regex);
        if (compile == null) {
            return null;
        }
        return compile.matcher(value);
    }

    /**
     * 获取html内容
     * @param url
     * @param charset
     * @return
     */
    private String getValueByHtml(String url, String charset) {
        String value = null;
        try {
            if (StringUtils.isBlank(url)) {
                return null;
            }
            HttpGet get = new HttpGet(url);
            HttpResponse execute = httpClient.execute(get);
            value = EntityUtils.toString(execute.getEntity(), charset);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return value;
    }

    /**
     * 传入url 以及匹配规则获取目标内容
     * @param beginUrl
     * @param targeRegex
     * @return
     */
    private void regex(String beginUrl) {
        T matchTactics = null;
        try {
            String value = getValueByHtml(beginUrl, "gbk");
            if (StringUtils.isBlank(value)) {
                return;
            }
            matchTactics = processor.matchTactics(value, targeRegex);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(matchTactics==null){
            return;
        }
        processor.processor(matchTactics, queue);
    }

    /**
     * 外部并发调用
     * @param urlQueue
     * @param threadNum
     * @return
     */
    public ArrayBlockingQueue<String> runReptile(final ArrayBlockingQueue<String> urlQueue, int threadNum) {
        try {
            ExecutorService pool = Executors.newFixedThreadPool(threadNum);
            CopyOnWriteArrayList<Future<String>> list = new CopyOnWriteArrayList<Future<String>>();
            while (!urlQueue.isEmpty()) {
                Future<String> submit = pool.submit(new Callable<String>() {
                    public String call() throws Exception {
                        regex(urlQueue.poll());
                        return "success";
                    }
                });
                list.add(submit);
            }
            int j = 0;
            for (Future<String> f : list) {
                if (f != null && "success".equals(f.get())) {
                    j++;
                }
            }
            System.out.println("成功获取:" + j + "条");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return queue;
    }

}
